package com.gitee.wsl.common.ui.draw.node

import androidx.annotation.FloatRange
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.PathEffect
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.DrawScope.Companion.DefaultBlendMode
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.unit.dp
import com.gitee.wsl.common.ui.base.ColorOrBrush
import com.gitee.wsl.common.ui.base.Point
import com.gitee.wsl.common.ui.draw.api.HasStroke
import com.gitee.wsl.common.ui.draw.api.HasTransform
import com.gitee.wsl.common.ui.draw.api.Transform
import com.gitee.wsl.common.ui.draw.container.GroupNode
import com.gitee.wsl.common.ui.symbol.generator.Curve
import com.gitee.wsl.mathematics.geometry.shape.Line

class LineNode(val node: Line, var pathEffect: PathEffect? = null): Node(),
    HasStroke,
    HasTransform {

    constructor(x1:Float=0f,
                y1:Float=0f,
                x2:Float=0f,
                y2:Float=0f):this(Line(Point(x1,y1), Point(x2,y2)))

    constructor(start: Point,
               end: Point):this(Line(start,end))

   override var transform: Transform? = null

   val x1 by node::x1
   val y1 by node::y1
   val x2 by node::x2
   val y2 by node::y2

    override fun DrawScope.draw() {
        strokeColor?.let {
            val start = Offset(x1.dp.toPx(), y1.dp.toPx())
            val end = Offset(x2.dp.toPx(), y2.dp.toPx())
            drawLine(
                it,
                start,
                end,
                strokeWidth = strokeWidth ?: Stroke.HairlineWidth,
                pathEffect = pathEffect
            )
            /*when (it) {
                is ColorOrBrush.Color -> drawLine(
                    it.value,
                    start,
                    end,
                    strokeWidth = strokeWidth ?: Stroke.HairlineWidth
                )
                is ColorOrBrush.Brush -> drawLine(
                    it.value,
                    start,
                    end,
                    strokeWidth = strokeWidth ?: Stroke.HairlineWidth
                )
            }*/
        }
    }
}

fun GroupNode.line(startPoint: Point, endPoint: Point = Point(), block: LineNode.(GroupNode)->Unit){
    val node = LineNode(Line(startPoint, endPoint))
    node.block(this)
    add(node)
}

fun GroupNode.line(x1:Float=0f,
                   y1:Float=0f,
                   x2:Float=0f,
                   y2:Float=0f, block: LineNode.(GroupNode)->Unit) = line(Point(x1, y1), Point(x2, y2),block
)

fun GroupNode.curve(curve: Curve,block: PathNode.(GroupNode)->Unit) {
    val node = PathNode(curve.path)
    node.block(this)
    add(node)
}

fun DrawScope.drawLine(
    colorOrBrush : ColorOrBrush,
    start: Offset,
    end: Offset,
    strokeWidth: Float = Stroke.HairlineWidth,
    cap: StrokeCap = Stroke.DefaultCap,
    pathEffect: PathEffect? = null,
    @FloatRange(from = 0.0, to = 1.0) alpha: Float = 1.0f,
    colorFilter: ColorFilter? = null,
    blendMode: BlendMode = DefaultBlendMode
){
    when (colorOrBrush) {
        is ColorOrBrush.Color -> drawLine(
            colorOrBrush.value,
            start,
            end,
            strokeWidth = strokeWidth,
            cap, pathEffect, alpha, colorFilter, blendMode
        )
        is ColorOrBrush.Brush -> drawLine(
            colorOrBrush.value,
            start,
            end,
            strokeWidth = strokeWidth,
            cap, pathEffect, alpha, colorFilter, blendMode
        )
    }
}